{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Singletonパターン\n",
    "\n",
    "* Singletonパターン\n",
    "    * 一つだけに限定されたインスタンスを複数のオブジェクト内で共有する場合に使う\n",
    "        * ログの書き込み処理を行うメソッドでのファイルへのアクセスするとき\n",
    "        * システム内で共有のキャッシュテーブルを参照するとき\n",
    "        * アプリケーションで一度だけ読めばいい設定ファイルの内容のコンテナ\n",
    "        * コネクションプーリングのように作成したインスタンスをプールして使いまわすとき\n",
    "    * 前提条件\n",
    "        * 作成したクラスは唯一1つだけのインスタンスを自身で作成する\n",
    "        * システム内のどこでもその一つだけのインスタンスにアクセスできる\n",
    "    * Singletonパターンの課題\n",
    "        * グローバル変数の代わりになると、複数箇所で変更されるとカオスになる\n",
    "        * コードが密結合になりやすく、テストを書きづらくなる\n",
    "    * Singletonモジュール\n",
    "        * Rubyの標準ライブラリ\n",
    "        * Mix-inしたクラスのインスタンスは常に同一のものを返すようになる"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "インスタンス変数counterが異なるインスタンス同士で共有されている\n",
      "1\n",
      "2\n"
     ]
    }
   ],
   "source": [
    "require 'singleton'\n",
    "\n",
    "class SingletonObject\n",
    "  # 「instance」メソッドが定義され、newメソッドがprivateに設定される\n",
    "  include Singleton\n",
    "  \n",
    "  attr_accessor :counter\n",
    "  \n",
    "  def initialize\n",
    "    @counter = 0\n",
    "  end\n",
    "end\n",
    "\n",
    "puts \"インスタンス変数counterが異なるインスタンス同士で共有されている\"\n",
    "obj1 = SingletonObject.instance\n",
    "obj1.counter += 1\n",
    "puts obj1.counter\n",
    "\n",
    "obj2 = SingletonObject.instance\n",
    "obj2.counter += 1\n",
    "puts obj2.counter"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Ruby 2.3.3",
   "language": "ruby",
   "name": "ruby"
  },
  "language_info": {
   "file_extension": ".rb",
   "mimetype": "application/x-ruby",
   "name": "ruby",
   "version": "2.3.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
